#pragma once

#include "thread.hpp"
#include "log.hpp"
#include "mutex.hpp"
#include "cond.hpp"
#include <memory>
#include <vector>
#include <queue>

namespace threadpoolmodule
{
    void test()
    {
        LOG(DEBUG) << "测试线程创建情况";
    }

    using thread_t = std::shared_ptr<threadmodule::thread>;
    const static int defaultnum = 5;

    template <class T>
    class threadpool
    {
    private:
        void TaskHandle(std::string name)
        { // 任务行为
            while (true)
            {
                T t;
                {
                    mutexmodule::lockgroud lock(_lock);
                    while (task_queue.empty()&&_isrunning)
                    {
                        _waitnum++;
                        _cond.wait(_lock.addr());
                        _waitnum--;
                    }
                    if(task_queue.empty()&&_isrunning==false)
                        break;
                    t = task_queue.front();
                    task_queue.pop();
                }
                t();
            }
        }

        threadpool(const threadpool<T>& pool)=delete;
        const threadpool<T>& operator=(const threadpool<T>& pool)=delete;

        threadpool(int num = defaultnum) : _num(num), _isrunning(false)
        {
            for (int i = 0; i < _num; i++)
            {
                threads.push_back(std::make_shared<threadmodule::thread>(std::bind(&threadpool::TaskHandle, this,std::placeholders::_1)));
            }
        }

    public:
        static threadpool<T>* GetInstance()
        {
            if(instance==nullptr){
                mutexmodule::lockgroud lock(InsMutex);
                if(instance==nullptr)
                {
                    instance=new threadpool<T>();
                }
            }
            return instance;
        }

        void equeue(T &t)
        {
            if (!_isrunning)
                return;
            task_queue.push(t);
            if (_waitnum != 0)
            {
                _cond.Nodify();
            }
        }

        void start()
        {
            if (_isrunning == false)
            {
                _isrunning=true;
                for (auto e : threads)
                {
                    e->start();
                    LOG(DEBUG) << e->name() << "成功启动";
                }
            }
        }

        void wait()
        {
            for (auto e : threads)
            {
                e->join();
                LOG(INFO) << e->name() << "回收成功";
            }
        }

        void stop()
        {
            if(_isrunning==true)
                _isrunning=false;
        }

        ~threadpool() {}

    private:
        int _num;                      // 线程个数
        std::vector<thread_t> threads; // 线程
        std::queue<T> task_queue;      // 任务队列
        mutexmodule::mutex _lock;      // 互斥锁
        condmodule::cond _cond;        // 条件变量
        int _waitnum;                  // 等待的线程个数
        bool _isrunning;               // 线程池是否在运行

        static threadpool<T>* instance; //单例
        static mutexmodule::mutex InsMutex;    //专用于单例的锁
    };

    template<typename T>
    threadpool<T>* threadpool<T>::instance=nullptr;

    template<typename T>
    mutexmodule::mutex threadpool<T>::InsMutex;   
}